package com.ningju.procurement.common.money;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

/**
 * 金额类
 */
@JsonSerialize(using = MoneySerializer.class)
public class Money implements Comparable<Money>, Serializable {
	
	/**/
	private static final long serialVersionUID = 3824538565923085574L;

	public static Money ZERO = new Money();

	private BigDecimal amount;

	public Money() {
		this(BigDecimal.ZERO);
	}
	
	public Money(String amount) {
		this(new BigDecimal(amount));
	}
	
	public Money(Double amount) {
		this(new BigDecimal(amount));
	}
	
	public Money(Integer amount) {
		this(new BigDecimal(amount));
	}

	public Money(BigDecimal decimal) {
		if (null == decimal) {
			decimal = BigDecimal.ZERO;
		}
		amount = decimal.setScale(2, BigDecimal.ROUND_HALF_EVEN);
	}
	
	public BigDecimal getAmount() {
		return amount;
	}
	
	/**
	 * 小于
	 * @param money
	 * @return
	 */
	public boolean lessThan(Money money) {
		return this.compareTo(money) < 0;
	}
	
	/**
	 * 大于
	 * @param money
	 * @return
	 */
	public boolean greaterThan(Money money) {
		return this.compareTo(money) > 0;
	}
	
	/**
	 * 比较大小
	 * return
	 * 		-1 比money小
	 * 		0 相等
	 * 		1 比money大
	 */
	public int compareTo(Money money) {
		return this.getAmount().compareTo(money.getAmount());
	}

	/**
	 * 金额间的加法
	 * @param two
	 * @return
	 */
	public Money add(Money two) {
		BigDecimal bigDecimal2 = this.getAmount();
		BigDecimal bigDecimal3 = two.getAmount();
		
		if(null == two || two.isZero()) {
			return this;
		}
		
		return new Money(bigDecimal2.add(bigDecimal3));
	}

	/**
	 * 金额间的减法
	 * @param two
	 * @return
	 */
	public Money subtract(Money two) {
		BigDecimal bigDecimal2 = this.getAmount();
		BigDecimal bigDecimal3 = two.getAmount();
		
		if(null == two || two.isZero() || this.isZero()) {
			return this;
		}
		
		Money result = new Money(bigDecimal2.subtract(bigDecimal3));
		
		return result.lessThan(Money.ZERO) ? Money.ZERO : result;
	}
	
	/**
	 * 金额与整数数量乘法
	 * @param quantity
	 * @return
	 */
	public Money multiply(int quantity) {
		BigDecimal money = this.getAmount();
		BigDecimal q = new BigDecimal(quantity);
		
		if(this.isZero()) {
			return this;
		}
		
		return new Money(money.multiply(q));
	}
	
	/**
	 * 金额与整数数量除法
	 * @param quantity
	 * @return
	 */
	public Money divide(int quantity) {
		BigDecimal money = this.getAmount();
		BigDecimal q = new BigDecimal(quantity);
		
		if(this.isZero() || quantity == 0) {
			return this;
		}
		
		return new Money(money.divide(q, 2, RoundingMode.HALF_EVEN));
	}
	
	/**
	 * 判断金额是否为0
	 * @return
	 */
	public boolean isZero() {
		return this.compareTo(new Money(BigDecimal.ZERO)) == 0;
	}
	
	/**
	 * 转换为单位“分”
	 * @return
	 */
	public BigInteger toCent() {
		if(this.isZero()) {
			return new BigInteger("0");
		}
		return amount.multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_EVEN).toBigInteger();
	}
	
	@Override
	public boolean equals(Object o) {
		if (this == o) {
            return true;
        }
        if (o == null) return false;
        if (!getClass().isAssignableFrom(o.getClass())) {
            return false;
        }

        Money money = (Money) o;

        if (amount != null ? !amount.equals(money.amount) : money.amount != null) {
            return false;
        }

        return true;
	}

	@Override
	public String toString() {
		return this.getAmount().toString();
	}
	
	/**
	 * 测试
	 * @param args
	 */
	public static void main(String[] args) {
		Money m = new Money(new BigDecimal(15.63));
		Money m2 = m.multiply(2).divide(2).subtract(new Money(new BigDecimal(3.33)));
		Money m3 = m2.add(new Money(new BigDecimal(3.33)));
		System.out.println(m.equals(m3));
	}
}
